package hust.hiepdv.javaproject.view;

import hust.hiepdv.javaproject.constant.Constant;
import hust.hiepdv.javaproject.model.Ball;
import hust.hiepdv.javaproject.model.DrawableObject;
import hust.hiepdv.javaproject.model.Pad;
import hust.hiepdv.javaproject.model.Table;
import hust.hiepdv.javaproject.networking.TCPClient;

import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

import javax.swing.JPanel;

public class DrawPanel extends JPanel implements Constant, Runnable {

	private BufferedImage bufferedImage;

	private Table table;
	private Ball ball;
	private ArrayList<DrawableObject> drawObjs = new ArrayList<DrawableObject>();
	private Pad pad1, pad2, pad3, pad4;
	private ArrayList<Pad> pads = new ArrayList<Pad>();
	boolean moveRight = false;
	boolean moveLeft = false;
	private boolean isPlaying = false;

	public DrawPanel() {
		setFocusable(true);
		addMouseListener(mouseAdapter);
		addKeyListener(keyAdapter);		
		this.ball = ClientView.ball;
		this.pad1 = ClientView.pad1;
		this.pad2 = ClientView.pad2;
		this.pad3 = ClientView.pad3;
		this.pad4 = ClientView.pad4;
	}

	public synchronized void initialize() {
		bufferedImage = new BufferedImage(StartGameFrame.WIDTH,
				StartGameFrame.HEIGHT, BufferedImage.TYPE_INT_RGB);

		table = new Table(0, 0, Table.STYLE_1);
		drawObjs.add(table);

		// pad1 = new Pad(200, 40, Pad.STYLE_1, Pad.HORIZONTAL);
		drawObjs.add(pad1);
		pads.add(pad1);
		// pad2 = new Pad(550, 100, Pad.STYLE_2, Pad.VERTICAL);
		drawObjs.add(pad2);
		pads.add(pad2);
		// pad3 = new Pad(100, 550, Pad.STYLE_3, Pad.HORIZONTAL);
		drawObjs.add(pad3);
		pads.add(pad3);
		// pad4 = new Pad(40, 250, Pad.STYLE_4, Pad.VERTICAL);
		drawObjs.add(pad4);
		pads.add(pad4);

		// ball = new Ball(200 + 12.5f, 350 + 12.5f, Ball.STYLE_1);
		// ball.setData(200 + 12.5f, 350 + 12.5f, Ball.STYLE_1);
	}

	public void checkForCollisions() {
	}

	public void update() {
		getPadMoved(TCPClient.id).move();
	}

	public synchronized void drawBuffer() {
		Graphics2D bufferGraphic = bufferedImage.createGraphics();
		for (DrawableObject obj : drawObjs) {
			bufferGraphic.drawImage(obj.getImage(), obj.getX(), obj.getY(),
					null);
		}
		bufferGraphic.drawImage(ball.getImage(), (int) ball.getX(),
				(int) ball.getY(), null);
		/*bufferGraphic.drawString(ball.toString() + moveLeft + moveRight, 200,
				200);
*/
		bufferGraphic.dispose();
	}

	public void drawScreen() {
		Graphics2D screenGraphic = (Graphics2D) this.getGraphics();
		screenGraphic.drawImage(bufferedImage, 0, 0, this);
		Toolkit.getDefaultToolkit().sync();
		screenGraphic.dispose();
	}

	public void startGame() {
		initialize();
		while (true) {
			try {
				checkForCollisions();
				update();
				drawBuffer();
				drawScreen();
				Thread.sleep(TIME_SLEEP);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public KeyAdapter keyAdapter = new KeyAdapter() {

		@Override
		public void keyPressed(KeyEvent key) {
			switch (key.getKeyCode()) {
			case KeyEvent.VK_RIGHT:
				moveRight = true;
				getPadMoved(TCPClient.id).setMoveRight(true);
				break;
			case KeyEvent.VK_LEFT:
				moveLeft = true;
				getPadMoved(TCPClient.id).setMoveLeft(true);
				break;
			default:
				break;
			}
		};

		@Override
		public void keyReleased(KeyEvent e) {
			switch (e.getKeyCode()) {
			case KeyEvent.VK_RIGHT:
				moveRight = false;
				getPadMoved(TCPClient.id).setMoveRight(false);
				break;
			case KeyEvent.VK_LEFT:
				moveLeft = false;
				getPadMoved(TCPClient.id).setMoveLeft(false);
				break;
			default:
				break;
			}
		};
	};

	public MouseAdapter mouseAdapter = new MouseAdapter() {
		public void mouseEntered(MouseEvent e) {
			requestFocusInWindow();
		};
	};
	
	public Pad getPadMoved(int id) {
		switch (id) {
		case 0:
			return pad1;
		case 1:
			return pad2;
		case 2:
			return pad3;
		case 3:
			return pad4;
		default:
			return null;
		}
	}

	@Override
	public void run() {
		this.isPlaying = true;
		this.startGame();
	}
	
	public void stop(){
		this.setIsPlaying(false);
	}
	
	public synchronized boolean isPlaying() {
		return this.isPlaying;
	}

	public synchronized void setIsPlaying(boolean b) {
		this.isPlaying = b;
	}
}
